//////////////////////////////////////////////////////////////////////
//
// File: Resolution.java
//
// Copyright (c) 2003-2006 TiVo Inc.
//
//////////////////////////////////////////////////////////////////////

package com.tivo.hme.sdk;

/**
 * Encapsulates the resolution of a region of the display or 
 * rendering buffer. This is an immutable class that cannot be
 * changed, once constructed.
 */
public class Resolution {

    private int width = 0;
    private int height = 0;
    private int pixelAspectNumerator = 1;
    private int pixelAspectDenominator = 1;

    public Resolution(	int theWidth,
                	int theHeight,
                	int thePixelAspectNumerator,
                	int thePixelAspectDenominator) {

	if (thePixelAspectDenominator == 0) {
	    throw new IllegalArgumentException("Denominator is zero");
	}

        this.width = theWidth;
        this.height = theHeight;
        this.pixelAspectNumerator = thePixelAspectNumerator;
        this.pixelAspectDenominator = thePixelAspectDenominator;

    } // Resolution()

    /**
     * Reads a string of the format "<W>x<H>-PAR=<N>/<D>", 
     * where W,H,N, and D are all integers. This string is 
     * the safe format as that returned by getParsableString().
     *
     * @throws IllegalArgumentException if spec is not well-formed
     */
    public Resolution(String spec) {

        int i1 = 0;
	int i2 = i1;
	int fieldCount = 0;
	int specLength = spec.length();

	for (fieldCount = 0; fieldCount < 4; ++fieldCount) {
	    
	    // Find the next number
	    if (fieldCount > 0) {
		i1 = i2;
	        while (   (i1 < specLength) 
		       && (!Character.isDigit(spec.charAt(i1)))) {
		    ++i1;
	        }
	    }
            i2 = i1 + 1;
	    while (   (i2 < specLength) 
		   && (Character.isDigit(spec.charAt(i2)))) {
		++i2;
	    }
	    if ((i1 >= specLength) || (i2 > specLength)) {
	        // bad spec
	        break;
	    }

	    // Extract the number
	    int num = -1;
	    try {
	        num = Integer.parseInt(spec.substring(i1, i2));
	    } catch (NumberFormatException e) {
	        // bad spec
	        break;
	    }
	    if (num < 0) {
	        // bad spec
	        break;
	    }

	    // Put the number in the correct field
	    switch (fieldCount) {
	        case 0: width = num;
	        break;
	        case 1: height = num;
	        break;
	        case 2: pixelAspectNumerator = num;
	        break;
	        case 3: pixelAspectDenominator = num;
	        break;
	    }
	} // while fieldCount

	if (fieldCount < 4) {
	    throw new IllegalArgumentException(
	    			"Illegal specification: " + spec);
	}

    } // Resolution()

    public boolean equals(Object thatObj) {

        if (!(thatObj instanceof Resolution)) {
	    return false;
	}
	Resolution that = (Resolution)thatObj;

	return ((this.width == that.width)
	    && (this.height == that.height) 
	    && (this.pixelAspectNumerator == that.pixelAspectNumerator) 
	    && (this.pixelAspectDenominator == that.pixelAspectDenominator));

    } // equals()

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public int getPixelAspectNumerator() {
        return pixelAspectNumerator;
    }

    public int getPixelAspectDenominator() {
        return pixelAspectDenominator;
    }

    public double getPixelAspectRatio() {
        return (1.0 * pixelAspectNumerator)/pixelAspectDenominator;
    }

    public int getSafeActionHorizontal() {
	// 5% on each side not safe for action
	return (width * 5 / 100);
    }

    public int getSafeActionVertical() {
	// 3.75% on top and bottom edges not safe for action
	return (height * 375 / 10000);
    }

    public int getSafeTitleHorizontal() {
	return 2 * getSafeActionHorizontal();
    }

    public int getSafeTitleVertical() {
	return 2 * getSafeActionVertical();
    }

    /**
     * Returns a string that can be parsed by Resolution(String).
     */
    public String getParsableString() {
	// No class name, et cetera
        return ""
	    + width + "x" + height
	    + "-PAR=" + pixelAspectNumerator + "/" + pixelAspectDenominator
	    ;
    }

    public StringBuffer toString(StringBuffer buf) {
        buf.append("" 
	    + width + "x" + height
	    + "-PAR=" + pixelAspectNumerator + "/" + pixelAspectDenominator
	    );
        return buf;
    }

    public String toString() {
	StringBuffer buf = new StringBuffer(25);
        return this.getClass().getName() + "[" + toString(buf) + "]" ;
    }

} // class Resolution


